home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 2 / Gold Medal Software Volume 2 (Gold Medal) (1994).iso / prog / asm_0_m.arj / CHGCOLOR.ASM < prev    next >
Assembly Source File  |  1988-04-12  |  25KB  |  500 lines

  1.                 Title   ChgColor
  2.                 page    60,132
  3. ;------------------------------------------------------------------------
  4. ; ChgColor - Changes the palette colors reisters on an EGA video board.
  5. ;           If no command line parameters are entered the registers are
  6. ;           reset to theie factory defaults.
  7. ;           Parameters should be in the following format:
  8. ;
  9. ;               reg:value
  10. ;
  11. ;                   reg     -   is the register number (0 - 15)
  12. ;                   value   -   The decimal value (color) for that register
  13. ;
  14. ;           The semi-colon is required to seperate the register number
  15. ;           from the value. (Actually any white space will do.)  Each entry
  16. ;           on the command line must be seperated by a space.
  17. ;
  18. ;           example:
  19. ;
  20. ;               chgcolor  2:45  4 15 7:196
  21. ;------------------------------------------------------------------------
  22.  
  23. CR              equ     13                  ;carriage return
  24. EOS             equ     0                   ;End of String
  25. MAX_REG         equ     15                  ;max valid register
  26. MAX_COLOR       equ     255                 ;max valid color
  27.  
  28. code            segment para public 'code'
  29.                 assume  cs:code, ds:code, es:code, ss:code
  30.                 org     100h
  31. start:
  32.                 jmp     chgcolor            ;skip data area
  33.  
  34. prog_name       db      10,13,'ChgColor - EGA color palette changer v 1.0'
  35.                 db      10,13,'$'
  36. prog_length     db      $-prog_name         ;length of program signiture
  37. author          db      'by John Toledo$'
  38.  
  39. ;user changable registers/colors
  40. user_colors     db      0                   ;black
  41.                 db      1                   ;Blue
  42.                 db      2                   ;Green
  43.                 db      3                   ;Cyan
  44.                 db      4                   ;Red
  45.                 db      5                   ;Magenta
  46.                 db      20                  ;Brown
  47.                 db      7                   ;Light Gray
  48.                 db      56                  ;Dark  Gray
  49.                 db      57                  ;Light Blue
  50.                 db      58                  ;Light Green
  51.                 db      59                  ;Light Cyan
  52.                 db      60                  ;Light Red
  53.                 db      61                  ;Light Magenta
  54.                 db      62                  ;Yellow
  55.                 db      63                  ;White
  56.  
  57. defaults        db      0                   ;Black
  58.                 db      1                   ;Blue
  59.                 db      2                   ;Green
  60.                 db      3                   ;Cyan
  61.                 db      4                   ;Red
  62.                 db      5                   ;Magenta
  63.                 db      20                  ;Brown
  64.                 db      7                   ;Light Gray
  65.                 db      56                  ;Dark  Gray
  66.                 db      57                  ;Light Blue
  67.                 db      58                  ;Light Green
  68.                 db      59                  ;Light Cyan
  69.                 db      60                  ;Light Red
  70.                 db      61                  ;Light Magenta
  71.                 db      62                  ;Yellow
  72.                 db      63                  ;White
  73.  
  74. old_int10       dd      ?
  75. ;------------------------------------------------------------------------
  76. ; new_int10 - intercepts calls to INT 10h BIOS calls.  If the request is
  77. ; going to attempt to change the EGA palette registers this routine will
  78. ; simply return.  This leave the user selected colors in place.
  79. ;------------------------------------------------------------------------
  80. hold_ah         db      ?
  81. new_int10       proc    far
  82.                 mov     cs:hold_ah,ah       ;save the requested action type
  83.                 pushf                       ;push flags to immulate INT call
  84.                 call    cs:old_int10        ;and do the call first thing
  85.  
  86.                 cmp     cs:hold_ah,10h      ;was the request a palette register
  87.                 je      reset_registers     ;change ?  If so, change 'em back
  88.                 cmp     cs:hold_ah,0bh
  89.                 je      reset_registers
  90.                 cmp     cs:hold_ah,0h
  91.                 je      reset_registers
  92.                 jmp     new_int10_exit      ;no changes, just leave
  93. reset_registers:
  94.                 push    si
  95.                 push    ds
  96.                 push    es
  97.  
  98.                 push    cs                  ;set segment registers
  99.                 pop     ds                  ;           to current segment
  100.                 push    cs
  101.                 pop     es
  102.  
  103.                 lea     si,user_colors      ;point to user selected colors
  104.                 call    set_registers       ;and reset palette register
  105.  
  106.                 pop     es
  107.                 pop     ds
  108.                 pop     si
  109. new_int10_exit:
  110.                 iret
  111. new_int10       endp
  112.  
  113. ;------------------------------------------------------------------------
  114. ; set_registers - set the EGA pallette registers to their factory
  115. ; defaults.  These defaults may be found in the table DEFAULTS.
  116. ;------------------------------------------------------------------------
  117. set_registers   proc    near
  118.                 push    bx
  119.                 mov     bx,0
  120. default_loop:
  121.                 mov     ah,byte ptr [si+bx] ;move color to AH register
  122.                 call    SetPaletteReg       ;set the pallette register
  123.                 inc     bx                  ;bump up to next register number
  124.                 cmp     bx,MAX_REG          ;done all 16 (base 0)
  125.                 jl      default_loop        ;nope, gon on
  126.                 pop     bx
  127.                 ret                         ;all done, lets go back
  128. set_registers   endp
  129.  
  130. ;------------------------------------------------------------------------
  131. ; SetPaletteReg - Sets an EGA color pallete register to the color
  132. ; specified.
  133. ;
  134. ;   BL - register number
  135. ;   AH - color
  136. ;------------------------------------------------------------------------
  137. SetPaletteReg   proc    near
  138.                 push    ax                  ;save registers
  139.                 push    bx
  140.                 push    cx
  141.                 push    dx
  142.                 push    es
  143. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  144. ;   The following commented code is here in case the need arises to do
  145. ;   the register change throught a BIOS call instead of the more hardware
  146. ;   dependent port reads and writes.
  147. ;
  148. ;                                           ;BL should have register number
  149. ;               mov     bh,ah               ;move color to BH
  150. ;               mov     ax,1000h            ;request set palette register
  151. ;               int     10h                 ;call BIOS
  152. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  153.  
  154.                 mov     ch,ah               ;save reg color
  155.  
  156.                 mov     ax,40h              ;load BIOS data segment address
  157.                 mov     es,ax               ;into ES
  158.                 mov     dx,es:[63h]         ;DX = CRTC address reg (3x4h)
  159.                 add     dl,6                ;DX = Status reg (3xah)
  160.                 push    dx                  ;preserve this value
  161.                 cli                         ;clear interrupts
  162.                 in      al,dx               ;reset Attribute Controller address
  163.                                             ;flip-flop
  164.                 mov     dl,0c0h             ;DX = 3c0h
  165.                 mov     al,bl               ;AL = PaletteRegNumber
  166.                 out     dx,al               ;update one palette register
  167.  
  168.                 mov     al,ch               ;AL = PaletteRegColor
  169.                 out     dx,al               ;set it
  170.                 pop     dx                  ;DX = status register port
  171.                 in      al,dx
  172.                 mov     dl,0c0h
  173.                 mov     al,20h              ;set bit 5 of
  174.                 out     dx,al               ; Attribute controller address reg
  175.  
  176.                 sti                         ;restart interrupts
  177.  
  178.                 pop     es                  ;restore registers
  179.                 pop     dx
  180.                 pop     cx
  181.                 pop     bx
  182.                 pop     ax
  183.  
  184.                 ret
  185. SetPaletteReg   endp
  186.  
  187. stay_res_mark   label   byte            ;keep stuff above resident
  188. ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  189. ; Non-memory resident code below.
  190. ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  191.  
  192. ;------------------------------------------------------------------------
  193. ; The following data was placed down here so it wouldn't remain resident.
  194. ;------------------------------------------------------------------------
  195. bad_reg_msg     db      10,13,'ERROR - invalid register number.',10,13,'$'
  196. bad_color_msg   db      10,13,'ERROR - invalid color number.',10,13,'$'
  197. no_color_msg    db      10,13,'ERROR - register not followed by color.'
  198.                 db      10,13,'$'
  199. defaults_msg    db      10,13,'Factory default colors restored.$'
  200. user_msg        db      10,13,'New colors set.$'
  201.  
  202. parm            db      80 dup(0)           ;temporary string area
  203. hold_reg        dw      ?                   ;temporary register area
  204.  
  205. ;------------------------------------------------------------------------
  206. ; chgcolor - main routine for changing EGA color palette registers.  It
  207. ; will reset the factory default colors if there are no command line
  208. ; parameters or set the user specified colors, if there are any, on the
  209. ; command line.
  210. ;------------------------------------------------------------------------
  211. chgcolor        proc    near
  212.                 lea     dx,prog_name        ;set up to display program name
  213.                 mov     ah,9                ;request DOS display string
  214.                 int     21h                 ;call DOS
  215.  
  216.                 mov     si,80h              ;point to parm count in PSP
  217.                 cmp     byte ptr [si],0h    ;anything there ?
  218.                 je      reset_colors        ;no, reset factory defaults
  219.                 inc     si                  ;make sure its not a blank line
  220.                 call    skip_delims         ;skip any white space out there
  221.                 cmp     byte ptr[si],CR     ;anything there ?
  222.                 je      reset_colors        ;no, reset factory defaults
  223.                 call    set_up_colors       ;yes, set new user colors
  224.                 jc      err_exit            ;exit if we had an error
  225.                 lea     si,user_colors      ;load addres of user EGA colors
  226.                 lea     dx,user_msg         ;show colors changed message
  227.                 jmp     leave               ;and exit
  228. reset_colors:
  229.                 lea     si,defaults         ;load addres of default EGA colors
  230.                 lea     di,user_colors      ;and copy it to the user table
  231.                 mov     cx,8                ;length of table in words
  232.                 cld                         ;move from left to right
  233.                 rep     movsw               ;and do it
  234.                 lea     si,defaults         ;load addres of default EGA colors
  235.                 lea     dx,defaults_msg     ;show defaults set message
  236. leave:
  237.                 mov     ah,9                ;request DOS display string
  238.                 int     21h                 ;and display color changes message
  239.                 call    set_registers       ;reset factory defaults
  240.  
  241.                 assume  es:nothing
  242.                 mov     ax,3510h            ;request get video vector address
  243.                 int     21h                 ;call DOS to do it
  244.                 mov     word ptr [old_int10],bx     ;save the offset
  245.                 mov     word ptr [old_int10+2],ES   ;save the segment
  246.  
  247.                 lea     si,prog_name                ;get offset of program
  248.                 mov     di,si                       ;signiture for comparison
  249.                 xor     ch,ch                       ;zero out CH
  250.                 mov     cl,prog_length              ;amount to compare
  251.                 rep     cmpsb                       ;do the compare
  252.                 jcxz    installed                   ;already instaled ?
  253.                                                     ;no, lets install
  254.                 mov     dx, offset new_int10        ;offset of new INT 10h
  255.                 mov     ax,2510h                    ;request DOS set vector
  256.                 int     21h                         ;call DOS to do it
  257.  
  258.                 lea     dx,stay_res_mark    ;load address of end of program
  259.                 int     27h                 ;old DOS terminate stay resident
  260. installed:
  261.                 lea     si,user_colors      ;load addres of user colors
  262.                 mov     di,si               ;to copy to mem res copy of program
  263.                 cld                         ;copy from left to right
  264.                 mov     cx,8                ;amount in words to copy
  265.                 rep     movsw               ;do the move
  266. err_exit:
  267.                 int     20h                 ;old DOS terminate program
  268. chgcolor        endp
  269.  
  270.  
  271. ;------------------------------------------------------------------------
  272. ; set_up_colors - sets the user requested colors.  It goes throught the
  273. ; command line list of registers and colors recursively calling the
  274. ; line parser until all of the command line has been processed.
  275. ; DI should be pointing to the beginning of the command line parameters.
  276. ;------------------------------------------------------------------------
  277. set_up_colors   proc    near
  278.                 lea     di,user_colors      ;set address of user table
  279.                 xor     bx,bx               ;set changed counter to zero
  280.                 call    get_reg             ;get reg number (returned in AX)
  281.                 cmp     byte ptr [si],CR    ;end of the command line ?
  282.                 je      no_color_err        ;yep, get out of here
  283.                 cmp     ax,MAX_REG          ;invalid register ?
  284.                 jle     good_reg            ;nope, keep going
  285.                 lea     dx,bad_reg_msg      ;set up to display register error
  286.                 call    display_err         ;display error messages
  287.                 jmp     set_colors_exit     ;lets leave now
  288. good_reg:
  289.                 mov     hold_reg,ax         ;save the register number
  290.                 call    get_color           ;get the color we need to set (AX)
  291.                 cmp     ax,MAX_COLOR        ;invalid color (not 0 - 255)
  292.                 jle     good_color          ;nope, keep going
  293.                 lea     dx,bad_color_msg    ;set up to display bad color error
  294.                 call    display_err         ;display error messages
  295.                 jmp     set_colors_exit     ;lets leave now
  296. good_color:
  297.                 mov     bx,hold_reg         ;move register number to BX
  298.                 mov     byte ptr [di+bx],al ;move color to user table
  299.                 cmp     byte ptr [si],CR    ;end of the command line ?
  300.                 je      set_colors_exit     ;yep, get out of here
  301.                 jmp     set_up_colors       ;no, get next guy to set
  302. no_color_err:
  303.                 lea     dx,no_color_msg     ;set up to display error
  304.                 call    display_err         ;and do it
  305.                 clc                         ;set carry to indicate error
  306.                 ret
  307. set_colors_exit:
  308.                 ret
  309. set_up_colors   endp
  310.  
  311. ;------------------------------------------------------------------------
  312. ; get_color - converts the string pointed to by DI into a binary number
  313. ; and places the number in AX.  It searches for a space, tab or carriage
  314. ; return which should follow a color number.
  315. ;------------------------------------------------------------------------
  316. get_color       proc    near
  317.                 push    cx
  318.                 push    di
  319.                 call    get_field           ;get the color number string
  320.                 lea     di,parm             ;point to start of color string
  321.                 cmp     byte ptr [di],EOS   ;was it the end of the line ?
  322.                 je      get_color_exit      ;yep, get out
  323.                 push    si                  ;save position in string
  324.                 lea     si,parm             ;reset SI to beginning of number
  325.                 call    atoi                ;convert it to binary (in AX)
  326.                 pop     si                  ;restore position in string
  327. get_color_exit:
  328.                 pop     di
  329.                 pop     cx
  330.                 ret
  331. get_color       endp
  332.  
  333. ;------------------------------------------------------------------------
  334. ; get_reg - converts the string pointed to by DI into a binary number
  335. ; and places the number in AX.  It searches for the ':' (colon) which
  336. ; should follow a register and places a 0 (end of string) in its place.
  337. ;------------------------------------------------------------------------
  338. get_reg         proc    near
  339.                 push    cx
  340.                 push    di
  341.                 call    get_field           ;get the register number string
  342.                 cmp     byte ptr [si],CR    ;was it the end of the line ?
  343.                 je      get_reg_exit        ;yep, get out
  344.                 push    si                  ;save position in string
  345.                 lea     si,parm             ;reset SI to beginning of number
  346.                 call    atoi                ;convert it to binary (in AX)
  347.                 pop     si                  ;restore position in string
  348. get_reg_exit:
  349.                 pop     di
  350.                 pop     cx
  351.                 ret
  352. get_reg         endp
  353.  
  354. ;------------------------------------------------------------------------
  355. ; get_field - gets the next parameter from a string pointed to by SI.
  356. ; Leaves SI pointing to the next position in the string and copies the
  357. ; parameter in the to the string parm.  Returns ax = 0ffffh if the parm
  358. ; is the last one in the string.
  359. ;------------------------------------------------------------------------
  360. get_field       proc    near
  361.                 push    di
  362.                 lea     di,parm             ;set up desination address
  363.                 call    skip_delims         ;go past leading spaces, tabs and :
  364. get_field_loop:
  365.                 cmp     byte ptr [si],CR    ;at end of command line parms ?
  366.                 je      get_field_exit      ;yep, get out of here
  367.                 cmp     byte ptr [si],' '   ;at end of command line parms ?
  368.                 je      get_field_exit      ;yep, get out of here
  369.                 cmp     byte ptr [si],':'   ;at end of command line parms ?
  370.                 je      get_field_exit      ;yep, get out of here
  371.                 mov     ah,byte ptr [si]    ;copy character 
  372.                 mov     byte ptr [di],ah    ;           to parm string
  373.                 inc     di                  ;bump up string pointers
  374.                 inc     si
  375.                 jmp     get_field_loop      ;and keep looking for more
  376. get_field_exit:
  377.                 mov     byte ptr [di],EOS   ;mark end of string
  378.                 pop     di
  379.                 ret
  380. get_field       endp
  381.  
  382. ;------------------------------------------------------------------------
  383. ; skip_delims - searches the string (area) pointed to by SI for the
  384. ; first non-white space.  It skips over spaces, tabs and colon characters
  385. ; and returns with SI pointed to the first non-white space.
  386. ;------------------------------------------------------------------------
  387. skip_delims     proc    near
  388.                 push    di                  ;save DI
  389.                 mov     cx,128              ;set CX to max string length
  390.                 mov     di,si               ;copy SI to DI for scasb call
  391.                 dec     di                  ;adjust for looping
  392.                 mov     al,' '              ;search for space
  393.                 cld                         ;set direction to go left to right
  394. keep_looking:
  395.                 inc     di                  ;point to next character
  396.                 repe    scasb               ;skip those blanks
  397.                 dec     di                  ;adjust DI to correct position
  398.                 cmp     byte ptr [di],9     ;is it a tab
  399.                 je      keep_looking        ;yep, we're done
  400.                 cmp     byte ptr [di],':'   ;is it a colon
  401.                 je      keep_looking        ;yep, we're done
  402. skip_delims_exit:
  403.                 mov     si,di               ;set SI to first non-white space
  404.                 pop     di                  ;restore DI
  405.                 ret
  406. skip_delims     endp
  407.  
  408. ;------------------------------------------------------------------------
  409. ; display_err - displays the message pointed to by the DX register and
  410. ; then displays the current contents of the temporary string parm.
  411. ;------------------------------------------------------------------------
  412. display_err     proc    near
  413.                 mov     ah,9                ;set up to display message
  414.                 int     21h                 ;call DOS to display message
  415.                 lea     di,parm             ;address of bad register string
  416. display_loop:
  417.                 cmp     byte ptr [di],EOS   ;end of the string ?
  418.                 je      display_exit        ;yep, let get out of here
  419.                 mov     ah,2                ;request DOS display character
  420.                 mov     dl,byte ptr [di]    ;move character to DL for DOS
  421.                 int     21h                 ;display that sucker
  422.                 inc     di                  ;point to next character
  423.                 jmp     display_loop        ;go get the next one
  424. display_exit:
  425.                 ret
  426. display_err     endp
  427.  
  428.  
  429. ;------------------------------------------------------------------------
  430. ; ATOI.ASM - convert ASCII string to 
  431. ;            16-bit decimal integer.
  432. ;
  433. ; Copyright 1987 Ziff Communications Co.
  434. ; Ray Duncan
  435. ; Call with:    DS:SI = address of string
  436. ;
  437. ;               where 'string' is in the form
  438. ;               
  439. ;                  [whitespace][sign][digits]
  440. ;
  441. ; Returns:      AX    = result
  442. ;               DS:SI = address+1 of terminator 
  443. ;
  444. ;               other registers preserved
  445. ;
  446. ; Like the C library 'atoi', this routine gives no 
  447. ; warning in the event of overflow, and terminates 
  448. ; on the first invalid character.
  449. ;------------------------------------------------------------------------
  450. blank           equ     20h             ; ASCII blank character
  451. tab             equ     09h             ; ASCII tab character
  452.  
  453. atoi            proc    near            ; ASCII to 16-bit integer
  454.                 push    bx              ; save registers
  455.                 push    cx
  456.                 push    dx
  457.                 xor     bx,bx           ; initialize forming answer
  458.                 xor     cx,cx           ; initialize sign flag
  459. atoi1:
  460.                 lodsb                   ; scan off whitespace
  461.                 cmp     al,blank        ; ignore leading blanks
  462.                 je      atoi1
  463.                 cmp     al,tab          ; ignore leading tabs
  464.                 je      atoi1
  465.                 cmp     al,'+'          ; if + sign proceed
  466.                 je      atoi2
  467.                 cmp     al,'-'          ; is it - sign?
  468.                 jne     atoi3           ; no, test if numeric
  469.                 dec     cx              ; was - sign, set flag
  470.                                         ; for negative result
  471. atoi2:
  472.                 lodsb                   ; get next character
  473. atoi3:
  474.                 cmp     al,'0'          ; is character valid?
  475.                 jb      atoi4           ; jump if not '0' to '9'
  476.                 cmp     al,'9'
  477.                 ja      atoi4           ; jump if not '0' to '9'
  478.                 and     ax,0fh          ; isolate lower four bits
  479.                 xchg    bx,ax           ; multiply answer x 10
  480.                 mov     dx,10
  481.                 mul     dx
  482.  
  483.                 add     bx,ax           ; add this digit
  484.                 jmp     atoi2           ; convert next digit
  485. atoi4:
  486.                 mov     ax,bx           ; result into AX
  487.                 jcxz    atoi5           ; jump if sign flag clear
  488.                 neg     ax              ; make result negative
  489. atoi5:
  490.                 pop     dx              ; restore registers
  491.                 pop     cx
  492.                 pop     bx
  493.  
  494.                 ret                     ; back to caller
  495. atoi            endp
  496.  
  497. code            ends
  498.                 end     start
  499.